/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.mahumLogs.utils;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.librairies.exceptions.CommandFailException;
import com.mahumLogs.backedbeans.Domain;
import com.mahumLogs.backedbeans.Log;
import com.mahumLogs.beans.ClientSSHBean;
import com.mahumLogs.beans.ConfigurationBean;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import org.primefaces.context.RequestContext;

/**
 *
 * @author Kalast
 */
@Named
@SessionScoped
public class LogsLector implements Serializable{

    private @Inject ClientSSHBean clientSSH;
    
    public LogsLector() {
        
    }
    
    public int getLastLineNumber(String filepath){
        try {
            Channel chan = this.clientSSH.execOnLogs("wc -l " + filepath);
            MyReader my_reader = new MyReader(new InputStreamReader(chan.getInputStream()));
            String result = my_reader.readLine().replace("\\s+", " ");
            System.err.println(result);
            result = result.trim().split(" ")[0];
            System.out.println(result);
            int line = Integer.valueOf(result);
            chan.disconnect();
            return line;  
        } catch (IOException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CommandFailException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        }
        return -1;
    }
    
    public int getNbLigneRemoteFile(String path){
        try {
            Channel chan = clientSSH.execOnLogs("wc -l " + path);
            MyReader my_reader = new MyReader(new InputStreamReader(chan.getInputStream()));
            String result = my_reader.readLine().replace("\\s+", " ");
            System.err.println(result);
            result = result.trim().split(" ")[0];
            System.out.println(result);
            int line = Integer.valueOf(result);
            my_reader.close();
            chan.disconnect();
            return line;
        } catch (IOException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CommandFailException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        }
        return -1;
    }
    
    public static LogsFile getLocalLogsFile(String path, String filename){
        LogsFile rfile = null;
        
        File directory = new File(path);
        if(directory.exists() && directory.isDirectory()){
            
        }
            
        return null;
    }
    
    public LogsFile getRemoteLogsFile(String path, String filename){
        LogsFile rfile = null;
        MyReader my_reader = null;
        Channel chan = null;
        try {
            System.out.println("exec " + SSH.cmdOS(SSH.COUNT_LINES_FILE, SSH.getValidPathFile(path + filename)));
            chan = clientSSH.execOnLogs(SSH.cmdOS(SSH.COUNT_LINES_FILE, SSH.getValidPathFile(path + filename)));
            my_reader = new MyReader(new InputStreamReader(chan.getInputStream()));
            String result = my_reader.readLine().replace("\\s+", " ");
            System.err.println(result);
            result = result.trim().split(" ")[0];
            System.out.println(result);
            rfile = new LogsFile();
            rfile.setNbLignes(Integer.valueOf(result));
            my_reader.close();
            chan.disconnect();
            path = SSH.getValidPathFile(path + filename);
            chan = clientSSH.execOnLogs("tail -1 " + path);
            my_reader = new MyReader(new InputStreamReader(chan.getInputStream()));
            String lastLine = my_reader.readLine();
            try{
                rfile.setEndTimestamp(new Date(Long.valueOf(lastLine.replace("\\s+", " ").split(" ")[0].replace(".", ""))));
                my_reader.close();
                chan.disconnect();
                chan = clientSSH.execOnLogs("head -1 " + path);
                my_reader = new MyReader(new InputStreamReader(chan.getInputStream()));
                String firstLine = my_reader.readLine();
                rfile.setStartTimestamp(new Date(Long.valueOf(firstLine.replace("\\s+", " ").split(" ")[0].replace(".", ""))));
                rfile.setPath(path);
                rfile.setFilename(filename);
            } catch(java.lang.NullPointerException nulex){
                System.err.println("Fichier de logs " + path + " invalide !");
                FacesMessage msg = new FacesMessage("Fichier invalide", "Fichier de logs " + path + " invalide !");
                msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                FacesContext.getCurrentInstance().addMessage(null, msg);
                RequestContext.getCurrentInstance().update("growl");
                rfile = null;
            }
            my_reader.close();
            chan.disconnect();    
        } catch (IOException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CommandFailException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return rfile;
    }
    
    public List<LogsFile> detectLogsFile(String path, String filename){
        ArrayList<LogsFile> logsFile = new ArrayList();
            try {           
                path = SSH.getValidPathFile(path);
                Channel chan = clientSSH.execOnLogs(SSH.cmdOS(SSH.LIST_FILES, path));
                MyReader my_reader = new MyReader(new InputStreamReader(chan.getInputStream()));
                String result;
                while((result = my_reader.readLine()) != null){
                    System.out.println(result);
                    if(result.contains(filename)){
                        System.err.println(result);
                        LogsFile file = this.getRemoteLogsFile(path, result);
                        if(file != null){
                            logsFile.add(file);
                        }
                    }            
                }
            } catch (IOException ex) {
                Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
            } catch (CommandFailException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        }
        
            
        Collections.sort(logsFile, new RemoteLogsFileComparator());   
        
        return logsFile;
    }
    
    public  String searchTimestamp(String address, String user, String pwd, String path, String timestamp){
        MyReader my_reader = null;
        String line = null;
        try {
            Channel chan = this.clientSSH.execOnLogs("grep -nombre '^" + timestamp + "' " + path + "*");
            my_reader = new MyReader(new InputStreamReader(chan.getInputStream()));
            line = my_reader.readLine(); 
        } catch (IOException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CommandFailException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                my_reader.close();
            } catch (IOException ex) {
                Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return line;
    }
    
    public void downloadLogs(){
        
    }
    
    public int getNumLine(String address, String user, String pwd, String path, String filename){
        try {
            String timestamp = getLastTimestamp(filename);
            System.out.println("Timestamp : " + timestamp);
            Channel chan = this.clientSSH.execOnLogs("grep -n '^" + timestamp + "' '" + path + filename + "'");
            MyReader my_reader = new MyReader(new InputStreamReader(chan.getInputStream()));
            return Integer.valueOf(my_reader.readLine().split(":")[0]);
        } catch (IOException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CommandFailException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        }
        return -1;
    }
    
    public static String getLastTimestamp(String filename){
        return tail(new File(filename)).replace("\\s+", " ").split(" ")[0];
    }
    
    public String getLastTimestampRemote(String path){
        try {
            Channel chan = this.clientSSH.execOnLogs("tail -1 " + path);
            MyReader my_reader = new MyReader(new InputStreamReader(chan.getInputStream()));
            String lastLine = my_reader.readLine();
            return lastLine.replace("\\s+", " ").split(" ")[0];
        } catch (IOException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CommandFailException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return null;
    }
    public String getFirstTimestampRemote(String path){
        try {
            Channel chan = this.clientSSH.execOnLogs("head -1 " + path);
            MyReader my_reader = new MyReader(new InputStreamReader(chan.getInputStream()));
            String firstLine = my_reader.readLine();
            return firstLine.replace("\\s+", " ").split(" ")[0];
        } catch (IOException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CommandFailException ex) {
            Logger.getLogger(LogsLector.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return null;
    }
    
    
    public static String tail(File file) {
        RandomAccessFile fileHandler = null;
        try {
            fileHandler = new RandomAccessFile(file, "r");
            long fileLength = fileHandler.length() - 1;
            StringBuilder sb = new StringBuilder();

            for (long filePointer = fileLength; filePointer != -1; filePointer--) {
                fileHandler.seek(filePointer);
                int readByte = fileHandler.readByte();

                if (readByte == 0xA) {
                    if (filePointer == fileLength) {
                        continue;
                    }
                    break;

                } else if (readByte == 0xD) {
                    if (filePointer == fileLength - 1) {
                        continue;
                    }
                    break;
                }

                sb.append((char) readByte);
            }

            String lastLine = sb.reverse().toString();
            return lastLine;
        } catch (java.io.FileNotFoundException e) {
            e.printStackTrace();
            return null;
        } catch (java.io.IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            if (fileHandler != null) {
                try {
                    fileHandler.close();
                } catch (IOException e) {
                    /* ignore */
                }
            }
        }
    }
}